<?php

declare(strict_types=1);

namespace Monarch\View\Renderers;

use Monarch\Components\HasComponents;
use Monarch\HTTP\Request;
use Monarch\View\HasLayouts;
use Monarch\View\RendererInterface;

class HTMLRenderer implements RendererInterface
{
    use HasLayouts;
    use HasComponents;

    private ?string $content = null;
    private array $data = [];
    private Request $request;

    /**
     * Creates a new HTMLRenderer instance with a Request object set.
     */
    public static function createWithRequest(Request $request): static
    {
        $renderer = new static();
        $renderer->withRequest($request);

        return $renderer;
    }

    /**
     * Generates the output for the given route file.
     * At this point, the control file has already been loaded and executed,
     * and the results of the control can be set with the `withRouteParams` method.
     *
     * NOTE: The route file is the full path to the file.
     */
    public function render(string $routeFile): ?string
    {
        $hasRequest = $this->request instanceof Request;
        $contentHtml = $this->renderHTMLFile($routeFile);
        $contentHtml = $this->parseComponents($contentHtml);

        if (! $hasRequest) {
            return $contentHtml;
        }

        if (! $this->needsLayout()) {
            return $contentHtml;
        }

        $layoutHtml = $this->renderLayout($routeFile);
        $layoutHtml = $this->parseComponents($layoutHtml);

        // TODO: Allow for multiple named slots in the layout
        return str_replace('<slot></slot>', $contentHtml, (string) $layoutHtml);
    }

    /**
     * Sets the content and data to be used when rendering the view.
     * This is generated by the control file, if one exists.
     */
    public function withRouteParams(?string $content, array $data = []): self
    {
        $this->content = $content;
        $this->data = $data;

        return $this;
    }

    /**
     * Sets the Request object to be used when rendering the view.
     */
    public function withRequest(Request $request): self
    {
        $this->request = $request;

        return $this;
    }
}
